package com.york.utils.util;

import com.alibaba.fastjson.JSONObject;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description:
 * @Data: 2021/11/25 12:47
 * @Author: yangboxiong
 * @Version
 * @since JDK 1.8
 */
public class StringUtil {


    /**
     * 字符串左补0
     */
    public static String stringFillLeftZero(String str, int len) {
        if (str.length() < len) {
            StringBuffer sb = new StringBuffer(len);
            for (int i = 0; i < len - str.length(); i++) {
                sb.append('0');
                sb.append(str);
            }
            return new String(sb);
        } else {
            return str;
        }
    }

    /**
     * 功能：不定长参数,其中一个参数为null或空则返回true,负责返回false
     *
     * @param str
     * @return boolean
     */
    public static boolean isEmpty(String... str) {
        for (String s : str) {
            if (org.apache.commons.lang3.StringUtils.isEmpty(s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 功能：不定长参数,其中一个参数为null或空或为空格字符串则返回true,负责返回false
     *
     * @param str
     * @return boolean
     * 返回true
     * 返回false
     */
    public static boolean isBlank(String... str) {
        for (String s : str) {
            if (org.apache.commons.lang3.StringUtils.isBlank(s) || "null".equals(s.toLowerCase())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 功能：判断字符串是否是数值. 默认允许有正负号,默认允许有小数点
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        boolean sign = true;
        int point_bef = Integer.MAX_VALUE;// 小数点前有几位
        int point_aft = Integer.MAX_VALUE;// 小数点后有几位
        return isNumeric(str, sign, point_bef, point_aft);
    }

    /**
     * 功能：判断字符串是否是数值
     *
     * @param str
     * @param sign  是否允许有正负号
     * @param point 是否允许有小数点
     * @return
     */
    public static boolean isNumeric(String str, boolean sign, boolean point) {
        int point_bef = Integer.MAX_VALUE;// 小数点前有几位
        int point_aft = Integer.MAX_VALUE;// 小数点后有几位
        if (!point) {
            point_aft = 0;
        }
        return isNumeric(str, sign, point_bef, point_aft);
    }

    /**
     * 功能：判断字符串是否是数值
     *
     * @param str
     * @param sign      是否允许有正负号
     * @param point_bef 精度,小数点前有几位
     * @param point_aft 精度,小数点后有几位,如果为0,则为整数
     * @return
     */
    public static boolean isNumeric(String str, boolean sign, int point_bef,
                                    int point_aft) {
        if (StringUtil.isBlank(str)) {
            return false;
        }
        boolean point = true;// 是否允许小数点
        if (point_aft == 0) {
            point = false;// 不允许有小数点
        } else {
            point = true;
        }
        StringBuffer pat = new StringBuffer();
        if (sign) {
            pat.append("[+|-]?");
        }
        if (point_bef == 0) {
            pat.append("[0]");
        } else {
            pat.append("[0-9]{1,");
            pat.append(point_bef);
            pat.append("}");
        }
        if (point && str.indexOf(".") != -1) {// 允许小数点,并且有小数点
            pat.append("[.]");
            pat.append("[0-9]{1,");// 小数点后必须有一位
            pat.append(point_aft);
            pat.append("}");
        }
        Pattern pattern = Pattern.compile(pat.toString());
        if (!pattern.matcher(str).matches()) {
            return false;
        } else {// 排除如00.1,返回false
            if (str.indexOf(".") != -1
                    && str.substring(0, str.indexOf(".")).length() > 1
                    && Integer.valueOf(str.substring(0, str.indexOf("."))) == 0) {
                return false;
            } else {
                return true;
            }
        }
    }

    /**
     * 功能：查看字符串是否有这个子字符串
     *
     * @param str    主字符串
     * @param substr 字字符串
     * @return
     */
    public static boolean hasSubstring(String str, String substr) {
        if (str == null || substr == null) {
            return false;
        }
        int strLen = str.length();
        int substrLen = substr.length();
        for (int i = 0; (i + substrLen) <= strLen; i++) {
            if (str.substring(i, i + substrLen).equalsIgnoreCase(substr)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 功能：验证是否是正确的手机号
     *
     * @param mobile
     * @return
     */
    public static boolean isMobile(String mobile) {
        if (StringUtil.isBlank(mobile)) {
            return false;
        }
        return Pattern.matches("^(1[3|5|8])\\d{9}$", mobile);
    }

    /**
     * 功能：字符串不以"/"结尾，则在串尾加"/"
     *
     * @param s
     * @return
     */
    public static String addSlashInEnd(String s) {
        if (s != null) {
            s = s.trim();
            if (!s.endsWith("/")) {
                s = s + "/";
            }
        } else {
            s = "";
        }
        return s;
    }

    /**
     * 功能：字符串不以"/"结尾，则在串尾加"/";字符串如果以/开头,则去掉第一个/
     *
     * @return
     */
    public static String dealSlash(String s) {
        if (s != null) {
            s = s.trim();
            if (!s.endsWith("/")) {
                s = s + "/";
            }
            if (s.startsWith("/")) {
                s = s.substring(1, s.length());
            }
        } else {
            s = "";
        }
        return s;

    }

    /**
     * 功能：传入一个数字类型的参数，返回一个小数点后两位的小数
     *
     * @param parm
     */
    public static String ConverDouble(String parm) {
        if (isNumeric(parm, false, true)) {
            if (parm.indexOf(".") >= 0) {
                String value = parm.substring(parm.indexOf(".") + 1);
                if (value.length() == 1) {
                    return parm + "0";
                } else if (value.length() > 2) {
                    return parm.substring(0, parm.indexOf(".") + 1)
                            + value.substring(0, 2);
                } else {
                    return parm;
                }
            } else {
                return parm + ".00";
            }
        }
        return null;
    }


    /**
     * @param obj
     * @return String
     * @obj==null,或obj是空字符串，就返回参数ifEmptyThen，否则返回obj.toString。
     */
    public static String ifEmptyThen(Object obj, String ifEmptyThen) {
        String ret = "";
        if (obj == null || String.valueOf(obj) == "") {
            ret = ifEmptyThen;
        } else {
            ret = obj.toString();
        }
        return ret;
    }

    /**
     * 功能：传入一个对象，如果为null，则输出为"",如果不为null,就调用toString()方法
     *
     * @param
     */
    public static String filterNull(Object s) {
        if (s == null) {
            return "";
        } else {
            return s.toString();
        }
    }

    /**
     * 字符串左补空格
     *
     * @throws UnsupportedEncodingException
     */
    public static String stringFillLeftSpace(String str, int len) throws UnsupportedEncodingException {
        StringBuffer sb = new StringBuffer(len);
        if (!isEmpty(str)) {
            int strLen = str.getBytes("GBK").length;
            if (strLen < len) {
                for (int i = 0; i < len - strLen; i++) {
                    sb.append(" ");
                    sb.append(str);
                }
                return new String(sb);
            } else {
                return str;
            }
        } else {
            for (int i = 0; i < len; i++) {
                sb.append(" ");
            }
            return new String(sb);
        }
    }

    /**
     * 字符串右补空格
     *
     * @throws UnsupportedEncodingException
     */
    public static String stringFillRightSpace(String str, int len) throws UnsupportedEncodingException {
        StringBuffer sb = new StringBuffer(len);
        if (!isEmpty(str)) {
            int strLen = str.getBytes("GBK").length;
            if (strLen < len) {
                sb.append(str);
                for (int i = 0; i < len - strLen; i++) {
                    sb.append(" ");
                }
                return new String(sb);
            } else {
                return str;
            }
        } else {
            for (int i = 0; i < len; i++) {
                sb.append(" ");
            }
            return new String(sb);
        }
    }

    /**
     * trim全角空格
     *
     * @param str
     * @return
     */
    public static String trimChinese(String str) {
        return str.replace("　", "").trim();
    }

    /**
     * 获取客户端IP地址，使用反向代理服务器也可以正常获取到
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0
                || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0
                || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0
                || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (ipAddress.equals("127.0.0.1")) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ipAddress = inet.getHostAddress();
            }

        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
            // = 15
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        if (ipAddress == null) {
            ipAddress = "";
        }
        return ipAddress;
    }

    /**
     * 按参数名首字母ascii升序，组装QueryString格式的字符串,空值不参与
     *
     * @param is      空参数是否参与
     * @param params  参数map
     * @param outKeys 不参与签名参数
     * @return String
     */
    public static String buildSignSrc(boolean is, Map params, String... outKeys) {
        //不参与签名参数
        Map<String, String> outKeyMap = new HashMap<String, String>();
        for (String key : outKeys) {
            outKeyMap.put(key, key);
        }

        TreeMap<String, String> tempMap = new TreeMap<String, String>();
        for (Object key1 : params.keySet()) {
            String key = (String) key1;
            //不参与签名
            if (outKeyMap.get(key) != null) {
                continue;
            }
            // 空参数不参与签名的参数
            String value = StringUtil.filterNull(params.get(key));
            if (!is && StringUtil.isBlank(value)) {
                continue;
            }
            tempMap.put(key, value);
        }

        StringBuilder buf = new StringBuilder();
        for (String key : tempMap.keySet()) {
            buf.append(key).append("=").append(tempMap.get(key)).append("&");
        }
        String src = "";
        if (!StringUtil.isBlank(buf.toString())) {
            src = buf.substring(0, buf.length() - 1);
        }
        return src;
    }

    /**
     * 按参数名首字母ascii升序，组装QueryString格式的字符串,空值不参与
     *
     * @param is      空参数是否参与
     * @param params  参数map
     * @param outKeys 空值参与签名参数
     * @return String
     */
    public static String buildSignSrcs(boolean is, Map params, String... outKeys) {
        //不参与签名参数
        Map<String, String> outKeyMap = new HashMap<String, String>();
        for (String key : outKeys) {
            outKeyMap.put(key, key);
        }

        TreeMap<String, String> tempMap = new TreeMap<String, String>();
        for (Object key1 : params.keySet()) {
            String key = (String) key1;
            // 空参数参与签名的参数
            String value = StringUtil.filterNull(params.get(key));
            tempMap.put(key, value);
        }
        StringBuilder buf = new StringBuilder();
        for (String key : tempMap.keySet()) {
            buf.append(key).append("=").append(tempMap.get(key)).append("&");
        }
        String src = "";
        if (!StringUtil.isBlank(buf.toString())) {
            src = buf.substring(0, buf.length() - 1);
        }
        return src;
    }

    /**
     * 验签
     *
     * @param md5Key key值
     * @param params 包含sign
     * @return true:成功 false:失败
     */
    public static boolean validSign(String md5Key, Map params) {
        String volidSign = (String) params.get("sign");
        String signStr = StringUtil.buildSignSrc(false, params, "sign") + "&key=" + md5Key;
        String sign = Md5.encrypt(signStr, "UTF-8");
        if (volidSign.equalsIgnoreCase(sign)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 按固定的参数顺序，组装QueryString格式的字符串
     *
     * @param params 参数map
     * @param keys   参数key数组
     * @param is     空参数是否参与
     * @return
     */
    public static String buildSignSrcStaticKeys(boolean is, Map<String, String> params, String[] keys) {
        StringBuilder buf = new StringBuilder();
        for (String key : keys) {
            String val = params.get(key);
            if (is) {
                buf.append(key).append("=").append(val).append("&");
            } else {
                if (!StringUtil.isBlank(val)) {
                    buf.append(key).append("=").append(val).append("&");
                }
            }

        }
        return buf.substring(0, buf.length() - 1);
    }

    /**
     * 指定字符转成JsonObject
     *
     * @param mapString
     * @param separator     移除字符
     * @param pairSeparator 指定字符进行分割
     * @return
     */
    public static JSONObject removeStrToMap(String mapString, String separator, String pairSeparator) {
        JSONObject returnJSON = new JSONObject();
        String[] fSplit = mapString.split(separator);
        for (int i = 0; i < fSplit.length; i++) {
            if (fSplit[i] == null || fSplit[i].length() == 0) {
                continue;
            }
            String[] sSplit = fSplit[i].split(pairSeparator);
            String value = fSplit[i].substring(fSplit[i].indexOf('=') + 1, fSplit[i].length());
            returnJSON.put(sSplit[0], value);
        }
        return returnJSON;
    }

    public static JSONObject getRequestMapValue(Map paramMap) {
        JSONObject jsonObject = new JSONObject(paramMap.size());
        for (Iterator iter = paramMap.entrySet().iterator(); iter.hasNext(); ) {
            Map.Entry element = (Map.Entry) iter.next();
            String strKey = (String) element.getKey();
            String[] strObj = (String[]) element.getValue();
            if (strObj != null) {
                jsonObject.put(strKey, strObj[0]);
            }
        }
        return jsonObject;

    }

    /**
     * 截取最后一个字符，按指定分隔符分割，返回数组
     *
     * @param str
     * @param splitStr
     * @return
     */
    public static String[] strSplitArray(String str, String splitStr) {
        str = str.substring(0, str.length() - 1);
        String[] strArray = str.split(splitStr);
        return strArray;
    }

    /**
     * 随机生成全球唯一UUID
     *
     * @return
     */
    public static String genUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    }


    /**
     * map封装成get请求参数
     *
     * @param is 空参数是否参与拼接
     */
    public static String buildMap(Boolean is, Map<String, Object> map) {
        StringBuffer sb = new StringBuffer();
        if (map != null && map.size() > 0) {
            for (String key : map.keySet()) {
                String value = StringUtil.ifEmptyThen(map.get(key), "");
                if (!is && StringUtil.isBlank(value)) {
                    continue;
                } else {
                    sb.append(key).append("=").append(value).append("&");
                }
            }
        }
        return sb.toString().substring(0, sb.toString().length() - 1);
    }

    /**
     * 验证邮箱
     */
    public static boolean isEmail(String email) {
        if (null == email || "".equals(email)) {
            return false;
        }
        String regEx1 = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
        Pattern p = Pattern.compile(regEx1);
        Matcher m = p.matcher(email);
        if (m.matches()) {
            return true;
        } else {
            return false;
        }
    }

    //金额验证
    public static boolean isMoney(String str) {
        // 判断小数点后2位的数字的正则表达式
        Pattern pattern = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$");
        Matcher match = pattern.matcher(str);
        if (match.matches() == false) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 按参数名首字母ascii升序，组装QueryString格式的字符串,空值不参与
     *
     * @param params  参数map
     * @param outKeys 不参与签名参数
     * @return String
     */
    public static String buildSignSrc(Map params, String... outKeys) {
        //不参与签名参数
        Map<String, String> outKeyMap = new HashMap<String, String>();
        for (String key : outKeys) {
            outKeyMap.put(key, key);
        }
        TreeMap<String, String> tempMap = new TreeMap<String, String>();
        for (Object key1 : params.keySet()) {
            String key = (String) key1;
            //不参与签名
            if (outKeyMap.get(key) != null) {
                continue;
            }
            // 空参数不参与签名的参数
            String value = StringUtil.ifEmptyThen(params.get(key), "");
            if (StringUtil.isBlank(value)) {
                continue;
            }
            tempMap.put(key, value);
        }

        StringBuilder buf = new StringBuilder();
        for (String key : tempMap.keySet()) {
            buf.append(tempMap.get(key));
        }
        return buf.toString();
    }
}